home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / byte-benchmarks / part05 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  21.6 KB

  1. Subject:  v22i032:  Byte Unix benchmarks, Part05/05
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: c5a9c6a9 eb24bf40 7bab71c5 9e371ee8
  5.  
  6. Submitted-by: "Ben Smith @ BYTE" <ben@bytepb.byte.com>
  7. Posting-number: Volume 22, Issue 32
  8. Archive-name: byte-benchmarks/part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 5)."
  17. # Contents:  dbmscli.c
  18. # Wrapped by rsalz@papaya.bbn.com on Tue May  8 08:55:34 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'dbmscli.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'dbmscli.c'\"
  22. else
  23. echo shar: Extracting \"'dbmscli.c'\" \(19728 characters\)
  24. sed "s/^X//" >'dbmscli.c' <<'END_OF_FILE'
  25. X
  26. X/*******************************************************************************
  27. X *  The BYTE UNIX Benchmarks - Release 2
  28. X *          Module: dbmscli.c   SID: 2.4 4/17/90 16:45:36
  29. X *          
  30. X *******************************************************************************
  31. X * Bug reports, patches, comments, suggestions should be sent to:
  32. X *
  33. X *    Ben Smith or Rick Grehan at BYTE Magazine
  34. X *    bensmith@bixpb.UUCP    rick_g@bixpb.UUCP
  35. X *
  36. X *****************************************************************************
  37. X *  Modification Log:
  38. X *
  39. X *    7/6/89 - Reworked messaging system so the semaphores were no
  40. X *    longer used in all cases.  Semaphores now only control the append
  41. X *    operation.  Messages contain caller's pid in type field.
  42. X *    The semaphore also serves to indicate the presence of the server. RG
  43. X *     
  44. X *    7/6/89 - added some debugging output to VERBOSE
  45. X *    7/9/89 - ifdef code that starts server from client - problems. BSS
  46. X *    7/11/89 - Added semaphore to set.  One semaphore controls the queue,
  47. X *    the other controls the append operation. RG
  48. X *      New command line format: dbmserv <filename> <queue size>
  49. X *****************************************************************************/
  50. X/*
  51. X * Multi-user DBMS simulation.
  52. X * Clients
  53. X * Database has the form:
  54. X * IIIINNNNNNNNNNNNNNNNNNNNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPPPPPPPP
  55. X * Where IIII is the 4-digit id number (0-padded)
  56. X *       NN... is the 20-character name
  57. X *       AA... is the 40-character address
  58. X *       PP... is the 10-character phone number
  59. X * Records are accessed by ID number (1 is the 0th record, 2 is 1st..etc.)
  60. X *
  61. X * This is the client system, which you execute with:
  62. X *      dbmscli n t i
  63. X * where:
  64. X *      n = the number of tasks to fork
  65. X *      t = is the sleep time in seconds each task waits between requests
  66. X *      i = is the number of test iterations
  67. X *
  68. X * NOTE: This version assumes Unix V compatibility.
  69. X */
  70. Xchar id[] = "@(#) @(#)dbmscli.c:1.5 -- 7/10/89 18:54:57";
  71. X
  72. X#include <stdio.h>
  73. X#include <ctype.h>
  74. X#include <errno.h>
  75. X#include <sys/types.h>
  76. X#include <sys/signal.h>
  77. X#include <sys/ipc.h>
  78. X#include <sys/sem.h>
  79. X#include <sys/msg.h>
  80. X#include <sys/param.h>
  81. X
  82. X#ifdef VERBOSE
  83. X#include <sys/times.h>
  84. X#define DEBUG    /* remove this after debugging */
  85. X#endif
  86. X
  87. X#define ERROR    (-1)
  88. X/*
  89. X** Record definitions.
  90. X*/
  91. X
  92. X#define IDLEN 4
  93. X#define NAMELEN 20
  94. X#define ADDRLEN 40
  95. X#define PHONLEN 10
  96. X#define RECLEN  74    /* Sum of the above. */
  97. X
  98. X/*
  99. X** Queue and semaphore names.
  100. X*/
  101. X#define    RQUEUE    "READ"        /* Read queue */
  102. X#define WQUEUE    "WRIT"        /* Write queue */
  103. X#define SEMA    "SEMA"        /* Semaphore name */
  104. X
  105. X/*
  106. X** Message types.
  107. X*/
  108. X#define READREQ    1        /* Read a record */
  109. X#define WRITEREQ 2        /* Write a record */
  110. X#define ADDREQ 3        /* Add a new record */
  111. X#define GETLREQ 4        /* Get largest record number */
  112. X#define RESULTREQ 10        /* Record contains results figures */
  113. X                /* Results are stored as:
  114. X                *  nnnnnnnnnnbmmmmmmmmmmb
  115. X                *   n = total time
  116. X                *   m = number of errors
  117. X                *   b = blank
  118. X                */
  119. X#define DIEREQ 99        /* Orders server to terminate. */
  120. X
  121. X
  122. X/*
  123. X** Return codes from the server.
  124. X*/
  125. X#define AOK 1            /* Request met ok */
  126. X#define DERR_RNF 2        /* Record not found */
  127. X#define DERR_RAE 3        /* Record already exists */
  128. X#define DERR_WRD 4        /* Unexplainable error */
  129. X#define DERR_UNK 9        /* Unknown request type */
  130. X
  131. X/*
  132. X** Error codes.
  133. X*/
  134. X#define QERR 1            /* Queue error */
  135. X#define SEMERR 2        /* Semaphore error */
  136. X
  137. X/*
  138. X** Structures.
  139. X*/
  140. X
  141. Xtypedef struct {
  142. X    char id[IDLEN];
  143. X    char name[NAMELEN];
  144. X    char address[ADDRLEN];
  145. X    char phone[PHONLEN];
  146. X} dbrec;
  147. X
  148. Xtypedef struct {
  149. X    int request;        /* Request type and response code */
  150. X    char recdat[RECLEN];    /* DBMS record data */
  151. X} msgdata;
  152. X
  153. Xtypedef struct {
  154. X    long type;        /* Hold's caller's pid */
  155. X    msgdata data;        /* Pointer to request and data */
  156. X} amess;
  157. X
  158. Xstruct ticker { unsigned long real,
  159. X               system,
  160. X               cpu; };
  161. X
  162. X/******************************************************************
  163. X      ####   #        ####   #####     ##    #        ####
  164. X     #    #  #       #    #  #    #   #  #   #       #
  165. X     #       #       #    #  #####   #    #  #        ####
  166. X     #  ###  #       #    #  #    #  ######  #            #
  167. X     #    #  #       #    #  #    #  #    #  #       #    #
  168. X      ####   ######   ####   #####   #    #  ######   ####
  169. X*******************************************************************/
  170. X/*
  171. X** Structure instances.
  172. X*/
  173. Xdbrec myrec;        /* Data record */
  174. Xamess myreq;        /* Client request */
  175. Xamess hisresp;        /* Response from server */
  176. X
  177. Xstruct sembuf unlockq = { 0 , 1 , SEM_UNDO };
  178. Xstruct sembuf lockq = { 0 , -1 , SEM_UNDO };
  179. Xstruct sembuf unlocka = { 0, 1, SEM_UNDO };
  180. Xstruct sembuf locka = { 0, -1, SEM_UNDO };
  181. X
  182. X#ifdef VERBOSE
  183. Xstruct tms tbuff;    /* For times system call */
  184. Xstruct ticker stopwatch = {0L, 0L, 0L};
  185. Xstruct ticker tottime = {0L, 0L, 0L};
  186. X#endif
  187. X
  188. Xint ntasks = 1;            /* Number of tasks */
  189. Xint sleeptime = 0;        /* Time to sleep */
  190. Xint iters = 1000;        /* iterations */
  191. Xint readq;            /* ID of read queue */
  192. Xint writeq;            /* ID of write queue */
  193. Xint qsema;            /* ID of semaphore for append */
  194. Xunsigned long errcnt;        /* Error count */
  195. Xint waitval;            /* Status return location for wait() */
  196. Xint rid;            /* ID chosen at random */
  197. Xint need_server;             /* flag for server */
  198. Xkey_t sema_key;
  199. X
  200. X/*
  201. X**  Externs and function defs.
  202. X*/
  203. Xlong randnum(), randwc();
  204. Xkey_t makey();
  205. X
  206. X/**************************************************************************
  207. X         #    #    ##       #    #    #
  208. X         ##  ##   #  #      #    ##   #
  209. X         # ## #  #    #     #    # #  #
  210. X         #    #  ######     #    #  # #
  211. X         #    #  #    #     #    #   ##
  212. X         #    #  #    #     #    #    #
  213. X****************************************************************************/
  214. Xmain(argc,argv,envp)
  215. Xint argc;
  216. Xchar *argv[];
  217. Xchar **envp;
  218. X{
  219. X
  220. X    int i,j,cerr;        /* Loop variables */
  221. X
  222. X    /*
  223. X    * Make sure we have proper input.
  224. X    */
  225. X    if(argc<2)
  226. X    {
  227. X    fprintf(stderr,
  228. X      "usage: %s datafile [ntasks] [sleeptime] [iter]\n",argv[0]);
  229. X    exit(1);
  230. X    }
  231. X
  232. X    /************* process command line parameters ************/
  233. X    /*
  234. X    * Get number of tasks and sleeptime.
  235. X    */
  236. X    if(argc==5)
  237. X        {
  238. X        if((iters=atoi(argv[4]))<=0)
  239. X
  240. X            {
  241. X            fprintf(stderr,"**Illegal iter\n");
  242. X            exit(1);
  243. X            }
  244. X        }
  245. X
  246. X    if(argc >=4)
  247. X    {
  248. X        if((sleeptime=atoi(argv[3]))<0)
  249. X            {
  250. X            fprintf(stderr,"**Illegal sleep time\n");
  251. X            exit(1);
  252. X            }
  253. X    }
  254. X
  255. X    if(argc >=3)
  256. X        {
  257. X        if((ntasks=atoi(argv[2]))<=0)
  258. X            {
  259. X            fprintf(stderr,"**Illegal ntasks\n");
  260. X            exit(1);
  261. X            }
  262. X        }
  263. X    
  264. X    /* argv[1] is the data file name */
  265. X
  266. X    /*
  267. X    * Make sure the server is active.
  268. X    */
  269. X
  270. X        sema_key=makey(SEMA);
  271. X    /* test to see if the server is already running */
  272. X    if((qsema=semget(sema_key,2,0))==ERROR)
  273. X        {
  274. X        int bad_news();
  275. X
  276. X        /* fork off for an exec to the server */
  277. X        if(!(j=fork())) /* this is the child aspiring to be */
  278. X            {    /* a server */
  279. X#ifdef DEBUG
  280. X            printf("I am the child (%d) aspiring to be a server\nn",
  281. X               getpid());
  282. X#endif
  283. X            argv[0]="dbmserv";
  284. X            execvp(argv[0],argv);
  285. X            /* if it gets this far, exec must have failed */
  286. X            perror("exec of dbmserv failed");
  287. X            exit(1);
  288. X            }
  289. X        /* better not do anything until the server
  290. X         * is running. Just wait for the server,
  291. X         * in this case a child process, gives us
  292. X         * signal to proceed.
  293. X         */
  294. X        signal(SIGALRM,bad_news);
  295. X        alarm(30); /* give the server 30 seconds to get it going */
  296. X        while ((qsema=semget(sema_key,1,0))==ERROR)
  297. X            {
  298. X#ifdef DEBUG
  299. X            printf("waiting for server\n");
  300. X#endif
  301. X            sleep(1);
  302. X            }
  303. X
  304. X                }    
  305. X
  306. X    /* get the message queue ids */
  307. X    if((readq=msgget(makey(RQUEUE),0))==ERROR)
  308. X        {
  309. X        qerror("Client getting read queue id");
  310. X        exit(1);
  311. X        }
  312. X#ifdef DEBUG
  313. X    else
  314. X        printf("read queue id is %d\n",readq);
  315. X#endif
  316. X    if((writeq=msgget(makey(WQUEUE),0))==ERROR)
  317. X        {
  318. X        qerror("Client getting write queue id");
  319. X        exit(1);
  320. X        }
  321. X#ifdef DEBUG
  322. X    else
  323. X        printf("write queue id is %d\n",readq);
  324. X#endif
  325. X    /*
  326. X    * Now fork off a bunch of processes, giving each
  327. X    * one a different starting seed.
  328. X    * (if fork() returns zero, this is already the child.
  329. X    */
  330. X    i=ntasks;
  331. X    do {
  332. X        j=fork();
  333. X    } while((j!=0)&&(--i!=0));
  334. X
  335. X    /*
  336. X    * Am I a child or a father?
  337. X    */
  338. X    if( j==0)
  339. X    {
  340. X#ifdef DEBUG
  341. X    printf("I am child client %d\n",getpid());
  342. X#endif
  343. X        /* ***Child process*** */
  344. X        if((cerr=dotests(i,iters))!=0)
  345. X        {
  346. X        fprintf(stderr,"**Child error:\n");
  347. X        switch(cerr)
  348. X           {
  349. X           case(QERR):
  350. X            qerror("    Error is");
  351. X            break;
  352. X           case(SEMERR):
  353. X            serror("    Error is");
  354. X            break;
  355. X           default:
  356. X            perror("    Error is");
  357. X            break;
  358. X           }
  359. X        exit(1);    /* If any error - just die. */
  360. X        }
  361. X        else
  362. X        {
  363. X        clearrec(myreq.data.recdat);
  364. X#ifdef VERBOSE
  365. X        /*
  366. X        ** Log net elapsed time.
  367. X        */
  368. X           sprintf(myreq.data.recdat,"%#010ld %#010ld %#010ld %#010d ",
  369. X            tottime.cpu,tottime.system,tottime.real,errcnt);
  370. X#else
  371. X           sprintf(myreq.data.recdat,"%#010d ", errcnt);
  372. X#endif
  373. X           myreq.type=RESULTREQ;
  374. X           if(semop(qsema,&lockq,1) == ERROR) exit(0);
  375. X           if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  376. X            exit(0);
  377. X           if(semop(qsema,&unlockq,1) == ERROR) exit(0);
  378. X
  379. X        exit(0);
  380. X        }
  381. X    }
  382. X    else
  383. X    {
  384. X#ifdef DEBUG
  385. X    printf("I am parent client %d\n",getpid());
  386. X#endif
  387. X        /* ***Father process*** */
  388. X        /*
  389. X        ** Wait for the children to complete.
  390. X        */
  391. X        i=ntasks;
  392. X        while(i--) wait(&waitval);
  393. X
  394. X        /*
  395. X        ** Now tell the server to go away.
  396. X        ** Note that if we have trouble (for some reason)
  397. X        ** getting the semaphore...we just barrel on through.
  398. X        */
  399. X        myreq.data.request=DIEREQ;
  400. X        myreq.type=1L; /* Pid not needed */
  401. X        if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  402. X            qerror("**Message queue error during termination\n");
  403. X        exit(0);
  404. X    }
  405. X}
  406. X
  407. X/********************************* dotests *************************
  408. X** Execute tests.
  409. X** Input number acts as seed for random number generator.
  410. X** Returns -1 if failure.
  411. X********************************************************************/
  412. Xint
  413. Xdotests(sseed,iter)
  414. Xint sseed;
  415. Xint iter;            /* Number of iterations */
  416. X{
  417. X
  418. X    int i,j;        /* Loop variables */
  419. X    int maxid;        /* Max ID currently in database */
  420. X    long mypid;        /* Get my process id */
  421. X
  422. X    /*
  423. X    ** Initialize the random number seed.
  424. X    */
  425. X    randnum((unsigned long)sseed);
  426. X
  427. X    /*
  428. X    ** Initialize error count and timer stuff.
  429. X    */
  430. X    errcnt=0;
  431. X
  432. X    /*
  433. X    ** I need to know my process id.
  434. X    */
  435. X    mypid = (long)getpid();
  436. X
  437. X    /*
  438. X    ** Find out what the maximum id in the database
  439. X    ** is.
  440. X    */
  441. X    myreq.data.request=GETLREQ;
  442. X    myreq.type=mypid;
  443. X#ifdef DEBUG
  444. X printf("About to send 1st transmission\n");
  445. X#endif
  446. X    if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  447. X    if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
  448. X    if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0) return(QERR);
  449. X    if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  450. X#ifdef DEBUG
  451. X printf("maxid string  = %s\n",hisresp.data.recdat);
  452. X#endif
  453. X    maxid=atoi(hisresp.data.recdat);
  454. X#ifdef DEBUG
  455. X printf("maxid = %d\n",maxid);
  456. X#endif
  457. X
  458. X    /*
  459. X    ** Now loop through the tests iter times.
  460. X    */
  461. X    for(i=0;i<iter;i++)
  462. X    {
  463. X#ifdef DEBUG
  464. X printf("In outer loop of client\n");
  465. X#endif
  466. X        /* Do 4 reads */
  467. X        for(j=0;j<4;j++)
  468. X        {
  469. X#ifdef DEBUG
  470. X printf("In inner loop of client\n");
  471. X#endif
  472. X            rid=(int)randwc(maxid)+1;
  473. X            clearrec(myreq.data.recdat);
  474. X            sprintf(myreq.data.recdat,"%#04d",rid);
  475. X            myreq.data.request=READREQ;
  476. X
  477. X#ifdef VERBOSE
  478. X            /* Turn on timer */
  479. X            stopwatch.real = times(&tbuff);
  480. X            stopwatch.system = tbuff.tms_stime;
  481. X            stopwatch.cpu = tbuff.tms_utime;
  482. X#endif
  483. X#ifdef DEBUG
  484. X            printf("About to read\n");
  485. X#endif
  486. X
  487. X            if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  488. X            if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  489. X                return(QERR);
  490. X            if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  491. X                return(QERR);
  492. X            if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  493. X
  494. X
  495. X#ifdef VERBOSE
  496. X            /* Turn off timer */
  497. X            tottime.real += times(&tbuff)-stopwatch.real;
  498. X            tottime.system += tbuff.tms_stime-stopwatch.system;
  499. X            tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  500. X
  501. X#endif
  502. X            /* Did we get what we should? */
  503. X            errcnt+=verify();
  504. X        }
  505. X
  506. X        /* Do 1 write */
  507. X        rid=(int)randwc(maxid)+1;
  508. X        clearrec(myreq.data.recdat);
  509. X        sprintf(myreq.data.recdat,"%#04d",rid);
  510. X        loadrec((rid-1)%10);
  511. X        strncpy(myreq.data.recdat+4,myrec.name,RECLEN-4);
  512. X        myreq.data.request=WRITEREQ;
  513. X
  514. X#ifdef VERBOSE
  515. X        /* Turn on timer */
  516. X        stopwatch.real = times(&tbuff);
  517. X        stopwatch.system = tbuff.tms_stime;
  518. X        stopwatch.cpu = tbuff.tms_utime;
  519. X#endif
  520. X
  521. X        if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  522. X        if(msgsnd(writeq,&myreq,RECLEN,0)<0)
  523. X            return(QERR);
  524. X        if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  525. X            return(QERR);
  526. X        if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  527. X#ifdef DEBUG
  528. X        printf("Message recieved\n");
  529. X#endif
  530. X
  531. X#ifdef VERBOSE
  532. X        /* Turn off timer */
  533. X        tottime.real += times(&tbuff)-stopwatch.real;
  534. X        tottime.system += tbuff.tms_stime-stopwatch.system;
  535. X        tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  536. X#endif
  537. X
  538. X        if(hisresp.data.request!=(long)AOK) errcnt++;
  539. X        /* Sleep a little */
  540. X        if(sleeptime) sleep(sleeptime);
  541. X
  542. X        /* Do an append every 10 times through the loop */
  543. X        if((i%10)==0)
  544. X        {
  545. X        myreq.data.request=GETLREQ;
  546. X
  547. X#ifdef VERBOSE
  548. X        /* Turn on timer */
  549. X        stopwatch.real = times(&tbuff);
  550. X        stopwatch.system = tbuff.tms_stime;
  551. X        stopwatch.cpu = tbuff.tms_utime;
  552. X#endif
  553. X        if(semop(qsema,&locka,1)==ERROR) return(SEMERR);
  554. X        if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  555. X        if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
  556. X        if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  557. X          return(QERR);
  558. X        if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  559. X
  560. X#ifdef VERBOSE
  561. X        /* Turn off timer */
  562. X        tottime.real += times(&tbuff)-stopwatch.real;
  563. X        tottime.system += tbuff.tms_stime-stopwatch.system;
  564. X        tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  565. X#endif
  566. X
  567. X        maxid=atoi(hisresp.data.recdat);
  568. X        rid=(maxid+=1);
  569. X        clearrec(myreq.data.recdat);
  570. X        sprintf(myreq.data.recdat,"%#04d",rid);
  571. X        loadrec((rid-1)%10);
  572. X        strncpy(myreq.data.recdat+4,myrec.name,RECLEN-4);
  573. X        myreq.data.request=ADDREQ;
  574. X
  575. X#ifdef VERBOSE
  576. X        /* Turn on timer */
  577. X        stopwatch.real = times(&tbuff);
  578. X        stopwatch.system = tbuff.tms_stime;
  579. X        stopwatch.cpu = tbuff.tms_utime;
  580. X#endif
  581. X
  582. X        if(semop(qsema,&lockq,1)==ERROR) return(SEMERR);
  583. X        if(msgsnd(writeq,&myreq,RECLEN,0)<0) return(QERR);
  584. X        if(msgrcv(readq,&hisresp,RECLEN,mypid,MSG_NOERROR)<0)
  585. X          return(QERR);
  586. X        if(semop(qsema,&unlockq,1)==ERROR) return(SEMERR);
  587. X        if(semop(qsema,&unlocka,1)==ERROR) return(SEMERR);
  588. X
  589. X#ifdef VERBOSE
  590. X        /* Turn off timer */
  591. X        tottime.real += times(&tbuff)-stopwatch.real;
  592. X        tottime.system += tbuff.tms_stime-stopwatch.system;
  593. X        tottime.cpu += tbuff.tms_utime-stopwatch.cpu;
  594. X#endif
  595. X
  596. X        if(hisresp.data.request!=(long)AOK) errcnt++;
  597. X
  598. X        /* Sleep a little */
  599. X        if(sleeptime) sleep(sleeptime);
  600. X
  601. X        }
  602. X    }
  603. X
  604. X    /*
  605. X    ** All's well that ends well.
  606. X    */
  607. X    return(0);
  608. X}
  609. X
  610. X/*
  611. X** verify
  612. X*/
  613. Xint verify()
  614. X{
  615. X    char buffr[80];
  616. X
  617. X    /* Is there response an error response? */
  618. X    if(hisresp.data.request!=(long)AOK)
  619. X     return(1);
  620. X
  621. X    /* Was it the number we were looking for? */
  622. X    strncpy(buffr,hisresp.data.recdat,4);
  623. X    buffr[4]='\0';
  624. X    if(atoi(buffr)!=rid) 
  625. X    return(1);
  626. X
  627. X    /* Check the record number with its contents */
  628. X    loadrec((rid-1)%10);
  629. X
  630. X    if(strncmp(hisresp.data.recdat+4,myrec.name,RECLEN-4)!=0)
  631. X        return(1);
  632. X
  633. X    /* Looks good */
  634. X    return(0);
  635. X}
  636. X
  637. X
  638. X/*
  639. X** Clear a record
  640. X*/
  641. Xclearrec(rptr)
  642. Xchar *rptr;
  643. X{
  644. X    int i;
  645. X
  646. X    for(i=0;i<RECLEN;++i)
  647. X        *rptr++='\0';
  648. X
  649. X     return;
  650. X}
  651. X
  652. X/*
  653. X** Load the record up with random data.
  654. X*/
  655. Xloadrec(sel)
  656. Xint sel;        /* Select which fake record */
  657. X
  658. X{
  659. X
  660. X    char *nname;
  661. X    char *naddr;
  662. X    char *nphon;
  663. X
  664. X    switch(sel)
  665. X    {
  666. X    case 0:    nname="Tom Thompson        ";
  667. X        naddr="9401 Billy Willy Road                   ";
  668. X        nphon="3334442222";
  669. X        break;
  670. X    case 1: nname="Steve Apiki         ";
  671. X        naddr="50 Hawaii Way c/o Jack Lord             ";
  672. X        nphon="1234443333";
  673. X        break;
  674. X    case 2: nname="Stan Diehl          ";
  675. X        naddr="27 Hoptoad Hollow Way                   ";
  676. X        nphon="3332221111";
  677. X        break;
  678. X    case 3: nname="Judy Grehan         ";
  679. X        naddr="Suite 3, WallState Building             ";
  680. X        nphon="9995556666";
  681. X        break;
  682. X    case 4: nname="Aaron Richards      ";
  683. X        naddr="Highway 40 OverPass, Second Pylon       ";
  684. X        nphon="8883339999";
  685. X        break;
  686. X    case 5: nname="Benjamin Davidson   ";
  687. X        naddr="Under The Bridge, HeavyWater City       ";
  688. X        nphon="7773229988";
  689. X        break;
  690. X    case 6: nname="Dayle Woolston      ";
  691. X        naddr="4040 Pleasant Way, WICAT Central        ";
  692. X        nphon="2228332299";
  693. X        break;
  694. X    case 7: nname="Jim Carls           ";
  695. X        naddr="Big Oak Tree Behind Barsodie's          ";
  696. X        nphon="32244566657";
  697. X        break;
  698. X    case 8: nname="Steve Smith         ";
  699. X        naddr="7000 Aloth Cove                         ";
  700. X        nphon="2118332929";
  701. X        break;
  702. X    case 9: 
  703. X    default: nname="Blind Willy Chitlins";
  704. X        naddr="Unavailable Until Further Notice        ";
  705. X        nphon="3456789012";
  706. X        break;
  707. X    }
  708. X
  709. X    /*
  710. X    ** Fill the structure with fake data.
  711. X    */
  712. X    strncpy(myrec.name,nname,NAMELEN);
  713. X    strncpy(myrec.address,naddr,ADDRLEN);
  714. X    strncpy(myrec.phone,nphon,PHONLEN);
  715. X
  716. X    return;
  717. X}
  718. X
  719. X/*
  720. X** randwc(num)
  721. X** Returns random modulo num.
  722. X*/
  723. Xlong randwc(num)
  724. Xlong num;
  725. X{
  726. X    return(randnum(0L)%num);
  727. X}
  728. X
  729. X/*
  730. X** randnum(val)
  731. X** Second order linear congruential generator.
  732. X** Constants suggested by J. G. Skellam.
  733. X** If val==0, returns next member of sequence.
  734. X**    val!=0, "seeds" generator with val.
  735. X*/
  736. Xlong randnum(lngval)
  737. Xunsigned long lngval;
  738. X{
  739. X    register unsigned long interm;
  740. X    static unsigned long randw[2] = { 13 , 117 };
  741. X
  742. X    if (lngval!=0L) randw[1]=lngval;
  743. X
  744. X    interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
  745. X    randw[1]=randw[0];
  746. X    randw[0]=interm;
  747. X    return(interm);
  748. X}
  749. X
  750. X/************************** makey ******************************
  751. X** Following routine converts an ASCII string to a key_t value.
  752. X** This routine originally appeared in ADVANCED PROGRAMMERS GUIDE
  753. X** TO UNIX SYSTEM V by R. Thomas, PHD; L. R. Rogers, and J. L. Yates.
  754. X** Osborne McGraw Hill.
  755. X*******************************************************************/
  756. Xkey_t
  757. Xmakey(p)
  758. Xchar *p;
  759. X{
  760. X    key_t keyv;
  761. X    int i;
  762. X
  763. X    if(isnumber(p))
  764. X        keyv = (key_t)atol(p);
  765. X    else
  766. X    {
  767. X        keyv=(key_t)0;
  768. X        for(i=0;i<sizeof(key_t) && p[i];i++)
  769. X            keyv=(keyv << 8) | p[i];
  770. X    }
  771. X    return(keyv);
  772. X}
  773. X
  774. X/***************************** isnumber *************************/
  775. Xint isnumber(p)
  776. Xchar *p;
  777. X{
  778. X    for( ; *p && isdigit(*p); p++) ;
  779. X    return(*p ? 0 : 1);
  780. X}
  781. X
  782. X/**************************** badnews **************************/
  783. Xint bad_news() /* things are screwed up */
  784. X{
  785. Xfprintf(stderr,"TIMED OUT\n");
  786. Xexit(1);
  787. X}
  788. X
  789. X/******************************** qerror **********************
  790. X ** prints out the errormessage associate with a queue
  791. X ***************************************************************/
  792. Xqerror(s)
  793. Xchar *s; /* message prefix string */
  794. X{
  795. Xextern int errno;
  796. X
  797. Xfprintf(stderr,"QUEUE ERROR: %s:\n     ",s);
  798. Xswitch(errno)
  799. X   {
  800. X   case EACCES: fprintf(stderr,
  801. X       "message queue exists, but locked out (EACCES)\n");
  802. X       break;
  803. X   case ENOENT: fprintf(stderr,
  804. X       "message queue does not exist (ENOENT)\n");
  805. X       break;
  806. X   case ENOSPC: fprintf(stderr,
  807. X       "too manny message queus (ENOSPC)\n");
  808. X       break;
  809. X   case EEXIST: fprintf(stderr,
  810. X       "message queue exists, but locked out (EEXIST)\n");
  811. X       break;
  812. X   default: fprintf(stderr,
  813. X       "unknown error (%n)",errno);
  814. X       break;
  815. X   }
  816. Xreturn(0);
  817. X}
  818. X
  819. X/******************************** serror **********************
  820. X ** prints out the errormessage associate with a semaphore
  821. X ***************************************************************/
  822. Xserror(s)
  823. Xchar *s; /* message prefix string */
  824. X{
  825. Xextern int errno;
  826. X
  827. Xfprintf(stderr,"SEMAPHORE ERROR: %s:\n     ",s);
  828. Xswitch(errno)
  829. X   {
  830. X   case EINVAL: fprintf(stderr,
  831. X       "invalid number of semaphore sets (EINVAL)\n");
  832. X       break;
  833. X   case EACCES: fprintf(stderr,
  834. X       "semaphore exists, but invalid operation (EACCES)\n");
  835. X       break;
  836. X   case ENOENT: fprintf(stderr,
  837. X       "semaphore does not exist (ENOENT)\n");
  838. X       break;
  839. X   case ENOSPC: fprintf(stderr,
  840. X       "too many semaphores (ENOSPC)\n");
  841. X       break;
  842. X   case EEXIST: fprintf(stderr,
  843. X       "semaphore exists, but locked out (EEXIST)\n");
  844. X       break;
  845. X   default: fprintf(stderr,
  846. X       "unknown error (%n)",errno);
  847. X       break;
  848. X   }
  849. Xreturn(0);
  850. X}
  851. END_OF_FILE
  852. if test 19728 -ne `wc -c <'dbmscli.c'`; then
  853.     echo shar: \"'dbmscli.c'\" unpacked with wrong size!
  854. fi
  855. chmod +x 'dbmscli.c'
  856. # end of 'dbmscli.c'
  857. fi
  858. echo shar: End of archive 5 \(of 5\).
  859. cp /dev/null ark5isdone
  860. MISSING=""
  861. for I in 1 2 3 4 5 ; do
  862.     if test ! -f ark${I}isdone ; then
  863.     MISSING="${MISSING} ${I}"
  864.     fi
  865. done
  866. if test "${MISSING}" = "" ; then
  867.     echo You have unpacked all 5 archives.
  868.     rm -f ark[1-9]isdone
  869. else
  870.     echo You still need to unpack the following archives:
  871.     echo "        " ${MISSING}
  872. fi
  873. ##  End of shell archive.
  874. exit 0
  875. exit 0 # Just in case...
  876.